<?php declare(strict_types=1);

use App\Models\Mysql\XnMerchant;
use Illuminate\Support\Arr;
use Illuminate\Http\JsonResponse;
use App\Models\Admin\Supplier as SupplierModel;
use Illuminate\Support\Facades\Config;

/**
 * 是否是手机号
 *
 * @param string $phone
 * @return false
 */
function isPhone(string $phone): bool
{
    return (bool) preg_match('/^1[0-9]{10}$/', $phone);
}

/**
 * @param Throwable $e
 * @return array
 */
function error2array(Throwable $e): array
{
    return [
        'message' => $e->getMessage(),
        'exception' => get_class($e),
        'file' => $e->getFile(),
        'line' => $e->getLine(),
        'trace' => collect($e->getTrace())->slice(0, 10)
            ->map(fn($trace) =>
                sprintf("%s[%s] %s %s %s", $trace['file'], $trace['line'] ?? '未知', $trace['class'] ?? '', $trace['type'] ?? '', $trace['function'] ?? '')
            )
            ->all(),
    ];
}

/**
 * @param array $array
 * @return false|string
 */
function array2json(array $array): bool|string
{
    return json_encode($array, 320);
}

/**
 * @param mixed $json
 * @return array
 */
function json2array(mixed $json): array
{
    if (!$json) {
        return [];
    }
    return json_decode($json, true) ?? [];
}

/**
 * @param mixed $xml
 * @return array
 */
function xml2array(mixed $xml): array
{
    try {
        if (!$xml) {
            return [];
        }
        $data = simplexml_load_string($xml);
        return json_decode(json_encode($data), true) ?? [];
    } catch (Throwable $e) {
        return [];
    }
}

/**
 * 加密字符串
 * @param string $data 字符串
 * @param string $key 加密key
 * @param string $cipher_algo 加密方式
 * @param int $options
 * @param string $iv
 * @param bool $base64 是否base64
 * @return string|false
 */
function encryptWithOpenssl(
    string $data,
    string $key,
    string $cipher_algo = 'AES-256-ECB',
    int    $options = OPENSSL_RAW_DATA,
    string $iv = '',
    bool   $base64 = true
): bool|string
{
    $str = openssl_encrypt($data, $cipher_algo, $key, $options, $iv);
    return $base64 ? base64_encode($str) : $str;
}

/**
 * 解密
 *
 * @param string $data
 * @param string $key
 * @param string $cipher_algo
 * @param int $options
 * @param string $iv
 * @param bool $base64
 * @return false|string
 */
function decryptWithOpenssl(
    string $data,
    string $key,
    string $cipher_algo = 'AES-256-ECB',
    int    $options = OPENSSL_RAW_DATA,
    string $iv = '',
    bool   $base64 = true
): bool|string
{
    return openssl_decrypt($base64 ? base64_decode($data) : $data, $cipher_algo, $key, $options, $iv);
}

/**
 * 毫秒时间戳
 *
 * @return int
 */
function millisecondTimestamp(): int
{
    list($time, $sec) = explode(' ', microtime());
    return intval(sprintf('%.0f', (floatval($time) + floatval($sec)) * 1000));
}


/**
 * @param string $message
 * @param int $code
 * @param mixed $info
 * @return JsonResponse
 */
function fails(string $message, int $code = 2, mixed $info = []): JsonResponse
{
    $headers = ['Content-Type' => 'application/json;charset=UTF-8', 'charset' => 'utf-8'];
    $arr = [
        'code' => $code,
        'message' => $message,
        'data' => $info
    ];
    return response()->json($arr, 200, $headers, JSON_UNESCAPED_UNICODE);
}

/**
 * @param mixed $info
 * @param int $code
 * @param string $message
 * @return JsonResponse
 */
function successly(mixed $info = [], int $code = 200, string $message = '成功'): JsonResponse
{
    $headers = ['Content-Type' => 'application/json;charset=UTF-8', 'charset' => 'utf-8'];
    $arr = [
        'code' => $code,
        'message' => $message,
        'data' => $info
    ];
    return response()->json($arr, 200, $headers, JSON_UNESCAPED_UNICODE);
}


/**
 * 使用curl方式实现get或post请求
 * @param string $url 请求的url地址
 * @param mixed $data 发送的post数据 如果为空则为get方式请求
 * return 请求后获取到的数据
 */
function curlRequest($url, $data = '')
{
    $ch = curl_init();
    $params[CURLOPT_URL] = $url;    //请求url地址
    $params[CURLOPT_HEADER] = false; //是否返回响应头信息
    $params[CURLOPT_RETURNTRANSFER] = true; //是否将结果返回
    $params[CURLOPT_FOLLOWLOCATION] = true; //是否重定向
    $params[CURLOPT_TIMEOUT] = 30; //超时时间
    if (!empty($data)) {
        $params[CURLOPT_POST] = true;
        $params[CURLOPT_POSTFIELDS] = $data;
    }
    $params[CURLOPT_SSL_VERIFYPEER] = false;//请求https时设置,还有其他解决方案
    $params[CURLOPT_SSL_VERIFYHOST] = false;//请求https时,其他方案查看其他博文
    curl_setopt_array($ch, $params); //传入curl参数
    $content = curl_exec($ch); //执行
    curl_close($ch); //关闭连接
    return $content;
}

function curlcheng_post($url, $data)

{
    $curl = curl_init();

    curl_setopt($curl, CURLOPT_URL, $url);

    curl_setopt($curl, CURLOPT_HEADER, 0);//不抓取头部信息。只返回数据

    curl_setopt($curl, CURLOPT_TIMEOUT, 10);//超时设置

    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//1表示不返回bool值

    curl_setopt($curl, CURLOPT_POST, 1);

    curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));//重点

    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));

    $response = curl_exec($curl);

    if (curl_errno($curl)) {
        return curl_error($curl);

    }

    curl_close($curl);

    return $response;
}


/**
 * @param array $array
 * @return bool|string
 */
function asc_sort(array $array): bool|string
{
    if (empty($array)) {
        return false;
    }
    ksort($array);
    $str = '';
    foreach ($array as $k => $val) {
        $str .= $k . '=' . $val . '&';
    }
    return rtrim($str, '&');
}

/**
 * 获取当前域名
 * @return string
 */
function getHttpType(): string
{
    $http = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';
    return $http . $_SERVER['HTTP_HOST'];
}

/**
 * @param string $startDate
 * @param string $endDate
 * @return array
 */
function getDateFromRange(string $startDate, string $endDate): array
{

    $startTimestamp = strtotime($startDate);
    $endTimestamp = strtotime($endDate);
    // 计算日期段内有多少天
    $days = ($endTimestamp - $startTimestamp) / 86400 + 1;
    // 保存每天日期
    $date = array();
    for ($i = 0; $i < $days; $i++) {
        $date[] = date('Y-m-d', $startTimestamp + (86400 * $i));
    }
    return $date;
}

/**
 * @param array $array
 * @param string $keys
 * @param string $sort
 * @return array
 */
function arraySort(array $array, string $keys, string $sort = 'desc'): array
{
    $newArr = $valArr = array();
    foreach ($array as $key => $value) {
        $valArr[$key] = $value[$keys];
    }
    ($sort == 'asc') ? asort($valArr) : arsort($valArr);
    foreach ($valArr as $key => $value) {
        $newArr[$key] = $array[$key];
    }
    return array_values($newArr);
}

/**
 * 检测db是否注册config
 *
 * @param string $dbKey
 * @return false|string
 */
function checkDbConnectIsRegister(string $dbKey): bool|string
{
    return empty(Config::get('database.connections.' . $dbKey, []));
}

/**
 * db注册config
 *
 * @param SupplierModel|int $supplier 供应商
 * @return mixed
 */
function dbRegister(SupplierModel|int $supplier): mixed
{
    /** @var SupplierModel|null $supplier * */
    if (! $supplier instanceof SupplierModel) {
        $supplier = SupplierModel::query()->find($supplier);
    }
    if (!$supplier) {
        return false;
    }
    return $supplier->registerDbConnect();
}

/**
 * db-connect-key
 *
 * @param SupplierModel|int $sid 供应商
 * @return string
 */
function dbConnectKey(SupplierModel|int $sid): string
{
    return'supplier@'. ($sid instanceof SupplierModel ? $sid->id : $sid);
}

/**
 * 接口加密方式sign
 */
function isSign($info){
    $secret_key = XnMerchant:: where('Merchant_number',$info['merchant_number']) -> value('secret_key');
    $old_sign = $info['sign'];
    $info = array_filter($info, function ($item) {
        return !empty($item);
    });
    unset($info['sign']);
    ksort($info);
    $new_sign = md5(json_encode($info).$secret_key);
    if($old_sign != $new_sign){
        return false;
    }
    return true;
}

/**
 * 将数值金额转换为中文大写金额
 * @param $amount float 金额(支持到分)
 * @param $type   int   补整类型,0:到角补整;1:到元补整
 * @return mixed 中文大写金额
 */
function Number_conversion_to_uppercase($amount, $type = 1) {
    // 判断输出的金额是否为数字或数字字符串
    if(!is_numeric($amount)){
        return "要转换的金额只能为数字!";
    }

    // 金额为0,则直接输出"零元整"
    if($amount == 0) {
        return "人民币零元整";
    }

    // 金额不能为负数
    if($amount < 0) {
        return "要转换的金额不能为负数!";
    }

    // 金额不能超过万亿,即12位
    if(strlen($amount) > 12) {
        return "要转换的金额不能为万亿及更高金额!";
    }

    // 预定义中文转换的数组
    $digital = array('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖');
    // 预定义单位转换的数组
    $position = array('仟', '佰', '拾', '亿', '仟', '佰', '拾', '万', '仟', '佰', '拾', '元');

    // 将金额的数值字符串拆分成数组
    $amountArr = explode('.', $amount);

    // 将整数位的数值字符串拆分成数组
    $integerArr = str_split($amountArr[0], 1);

    // 将整数部分替换成大写汉字

    $integerArrLength = count($integerArr);     // 整数位数组的长度
    $positionLength = count($position);         // 单位数组的长度
    for($i = 0; $i < $integerArrLength; $i++) {
        // 如果数值不为0,则正常转换
        if($integerArr[$i] != 0){
            $result =   $digital[$integerArr[$i]] . $position[$positionLength - $integerArrLength + $i];
        }else{
            // 如果数值为0, 且单位是亿,万,元这三个的时候,则直接显示单位
            if(($positionLength - $integerArrLength + $i + 1)%4 == 0){
                $result = $position[$positionLength - $integerArrLength + $i];
            }
        }
    }

    // 如果小数位也要转换
    if($type == 0) {
        // 将小数位的数值字符串拆分成数组
        $decimalArr = str_split($amountArr[1], 1);
        // 将角替换成大写汉字. 如果为0,则不替换
        if($decimalArr[0] != 0){
            $result = $result . $digital[$decimalArr[0]] . '角';
        }
        // 将分替换成大写汉字. 如果为0,则不替换
        if($decimalArr[1] != 0){
            $result = $result . $digital[$decimalArr[1]] . '分';
        }
    }else{
        $result = $result . '整';
    }
    return $result;
}
